#include "tcpmgr.h"
#include "usermgr.h"

#include <QJsonDocument>
#include <QJsonObject>

TcpMgr::TcpMgr()
    : _host(""), _port(0), _b_recv_pending(false), _message_id(0), _message_len(0)
{
    // 请求建立连接
    QObject::connect(&_socket, &QTcpSocket::connected, this, [&](){
        qDebug() << "Connected to server!" ;
        emit sig_con_success(true);
    });

    // 读取数据
    QObject::connect(&_socket, &QTcpSocket::readyRead, this, [&](){
        // 当有数据可读时，读取所有的数据
        // 读取所有数据并追加到缓冲区
        _buffer.append(_socket.readAll());

        QDataStream stream(&_buffer, QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_5_0);

        forever{
            // 先解析头部 4 bety
            if(_b_recv_pending == false){
                // 检查缓冲区中的数据是否足够解析出一个消息头（消息id + 消息长度）

                // 数据不多，等待更多的数据
                if(_buffer.size() < static_cast<int>(sizeof(quint16) * 2)) return;
                // 预读取消息id和消息长度，但不从缓冲区中移除
                stream >> _message_id >> _message_len;

                // 将buffer中的前四个字节移除
                _buffer = _buffer.mid(sizeof(quint16) * 2);
            }

            // buffer剩余长度是否满足消息长度，不满足则退出继续等待接受
            if(_buffer.size() < _message_len){
                _b_recv_pending = true;
                return;
            }
            _b_recv_pending = false;

            // 读取消息体
            QByteArray messageBody = _buffer.mid(0, _message_len);
            // qDebug() << "receive body msg is " << messageBody;
            // 回调逻辑
            if(_message_id == ReqId::ID_CHAT_LOGIN){

                qDebug() << "Message ID: " << _message_id << "(MSG_IDS::MSG_CHAT_LOGIN)" << ", Length: " << _message_len;
            }
            else if(_message_id == ReqId::ID_CHAT_LOGIN_RSP){
                handleMsg(ReqId::ID_CHAT_LOGIN_RSP, _message_len, messageBody); // 执行对应的回调函数
                // qDebug() << "Message ID: " << _message_id << "(MSG_IDS::MSG_CHAT_LOGIN_RSP)" << ", Length: " << _message_len;
            }

            _buffer = _buffer.mid(_message_len);
        }
    });

    // 处理错误
    // 5.15 之后的版本
    // QObject::connect(&_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred), [&](QAbstractSocket::SocketError socketError) {
    //     Q_UNUSED(socketError)
    //     qDebug() << "Error:" << _socket.errorString();
    // });
    // 5.15 之前的版本
    QObject::connect(&_socket, static_cast<void(QTcpSocket::*)(QTcpSocket::SocketError)>(&QTcpSocket::error), [&](QTcpSocket::SocketError socketError){
        qDebug() << "TcpMgr::_socket.connectToHost Error: ----------------------------" << _socket.errorString();
        switch(socketError){
        case QTcpSocket::ConnectionRefusedError:
            qDebug() << "connect refused!";
        case QTcpSocket::RemoteHostClosedError:
            qDebug() << "remote host closed coonnection!";
        case QTcpSocket::HostNotFoundError:
            qDebug() << "host not found!";
        case QTcpSocket::SocketTimeoutError:
            qDebug() << "connection timeout!";
        case QTcpSocket::NetworkError:
            qDebug() << "network error!";
        default:
            qDebug() << "other error!";
            break;
        }
    });

    // 断开连接的处理
    QObject::connect(&_socket, &QTcpSocket::disconnected, this, [&](){
        qDebug() << "disconnected from server!";
    });

    // ---> 请求 TcpMgr 向 ChatServer 发送数据
    QObject::connect(this, &TcpMgr::sig_send_data, this, &TcpMgr::slot_send_data);

    // 注册回调处理函数
    initHandlers();
}

// 连接对端服务器
void TcpMgr::slot_tcp_connect(ServerInfo chatServer){
    qDebug() << "receive tcp connect signal";
    // 尝试连接到服务器
    qDebug() << "connecting to srever...";
    _host = chatServer.Host;
    _port = static_cast<uint16_t>(chatServer.Port.toUInt());
    _socket.connectToHost(chatServer.Host, _port);
}

// 客户端通过 TcpMgr 向 ChatServer 发送数据
void TcpMgr::slot_send_data(ReqId reqId, QString data){
    uint16_t id = reqId;

    // 将字符串转化为UTF-8编码的字符数组
    QByteArray dataBytes = data.toUtf8();

    // 计算长度（使用网络字节序转化）
    quint16 len = static_cast<quint16>(data.size());

    // 创建一个QByteArray用于存储要发送的所有数据
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);

    // 设置数据流使用网络字节序
    out.setByteOrder(QDataStream::BigEndian);

    // 写入ID长度
    out << id << len;

    // 添加字符串数据
    block.append(data);

    // 发送数据
    _socket.write(block);
}

// 注册回调函数
void TcpMgr::initHandlers(){
    _handlers.insert(ID_CHAT_LOGIN_RSP, [this](ReqId id, int len, QByteArray data){
        qDebug() << "handler id is " << id << " data is " << data;
        // 将QByteArray转化为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);

        // 检查转化是否成功
        if(jsonDoc.isNull() == true){
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }

        QJsonObject jsonObj = jsonDoc.object();
        if(!jsonObj.contains("error")){
            int err = ErrorCodes::ERR_JSON;
            qDebug() << "Login Failed, err is Jaon Err" << err;
            emit sig_login_failed(err);
            return;
        }

        int err = jsonObj["error"].toInt();
        if(err != ErrorCodes::SUCCESS){
            qDebug() << "Login Failed, err is " << err;
            emit sig_login_failed(err);
            return;
        }

        // 存储用户信息
        UserMgr::GetInstance()->SetUid(jsonObj["uid"].toInt());
        UserMgr::GetInstance()->SetName(jsonObj["name"].toString());
        qDebug() << "169行  tcpmgr::initHandlers uid: " << jsonObj["uid"].toInt() << " name: " << jsonObj["name"].toString();
        UserMgr::GetInstance()->SetToken(jsonObj["token"].toString());
        emit sig_login_success(); // 跳转到聊天界面
    });
}
// 处理请求
void TcpMgr::handleMsg(ReqId id, int len, QByteArray data){
    auto find_iter = _handlers.find(id);
    if(find_iter == _handlers.end()){
        qDebug() << "not find id [" << id << "] to handle";
        return;
    }

    find_iter.value()(id, len, data); // 执行对应的回调函数
}
